package com.hopedove.tempdemo.utils

import android.graphics.*
import android.util.Size
import kotlin.math.max

data class TableSize(val rows: Int, val columns: Int)

/**
 *  织针排列
 */
class KnitArrangementHelper(
    private val aboveSize: TableSize,
    private val belowSize: TableSize? = null,
    private val aboveLeftMargin: Int = 0,
    private val belowLeftMargin: Int = 0,
    private val hasDivider: Boolean = false,
    private val cellSize: Size = Size(50, 50)
) {

    private var bitmap: Bitmap
    private val dividerSectionHeight = 15
    private val textPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        textSize = 20f
    }

    init {
        bitmap = buildTablesBitmap()
//        testDrawAbove()
//        testDrawBelow()
//        testDrawDivider()
//        testDrawCells()
    }


    private fun buildTablesBitmap(): Bitmap {
        val aboveWidth = aboveLeftMargin + aboveSize.columns * cellSize.width
        val belowWidth = belowSize?.let {
            belowLeftMargin + it.columns * cellSize.width
        } ?: -1

        val width = max(aboveWidth, belowWidth)

        val aboveHeight = aboveSize.rows * cellSize.height
        val belowHeight = belowSize?.let { it.rows * cellSize.height } ?: -1

        val height = if (belowHeight > 0) {
            aboveHeight + belowHeight + dividerSectionHeight
        } else {
            aboveHeight
        }
        val bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)

        // 如果有下表格，需要在上下表格中间画分割线
        if (belowSize != null && hasDivider) {
            val canvas = Canvas(bmp)
            val pathPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
                pathEffect = DashPathEffect(floatArrayOf(5f, 5f, 5f, 5f), 3f)
                color = Color.BLACK
                style = Paint.Style.STROKE
                strokeWidth = 2f
            }
            val path = Path().apply {
                moveTo(0f, (aboveSize.rows * cellSize.height + dividerSectionHeight / 2).toFloat())
                lineTo(
                    bmp.width.toFloat(),
                    (aboveSize.rows * cellSize.height + dividerSectionHeight / 2).toFloat()
                )
            }
            canvas.drawPath(path, pathPaint)
        }

        return bmp
    }

    private fun testDrawAbove() {
        val canvas = Canvas(bitmap)
        val paint = Paint().apply {
            style = Paint.Style.STROKE
            strokeWidth = 3f
            color = Color.GREEN
        }

        val rect = Rect(
            0,
            0,
            aboveLeftMargin + aboveSize.columns * cellSize.width,
            aboveSize.rows * cellSize.height
        )
        canvas.drawRect(rect, paint)
    }

    private fun testDrawBelow() {
        belowSize?.let { below ->
            val canvas = Canvas(bitmap)
            val paint = Paint().apply {
                style = Paint.Style.STROKE
                strokeWidth = 3f
                color = Color.RED
            }

            val dy = aboveSize.rows * cellSize.height + dividerSectionHeight
            val rect =
                Rect(
                    0,
                    below.rows * cellSize.height + dy,
                    belowLeftMargin + below.columns * cellSize.width,
                    bitmap.height
                )
            canvas.drawRect(rect, paint)
        }
    }

    private fun testDrawDivider() {
        belowSize?.let {
            val canvas = Canvas(bitmap)
            val paint = Paint().apply {
                style = Paint.Style.STROKE
                strokeWidth = 3f
                color = Color.CYAN
            }

            val dy = aboveSize.rows * cellSize.height
            val rect =
                Rect(
                    0,
                    dy,
                    bitmap.width,
                    dy + dividerSectionHeight
                )
            canvas.drawRect(rect, paint)
        }
    }

    private fun testDrawCells() {
        val canvas = Canvas(bitmap)
        val paint = Paint().apply {
            style = Paint.Style.STROKE
            strokeWidth = 1f
            color = Color.BLUE
        }
        for (row in 0 until aboveSize.rows) {
            for (col in 0 until aboveSize.columns) {
                val x = aboveLeftMargin + col * cellSize.width
                val y = row * cellSize.height
                val r = Rect(x, y, x + cellSize.width, y + cellSize.height)
                canvas.drawRect(r, paint)
            }
        }

        belowSize?.let {
            paint.color = Color.BLACK
            for (row in 0 until it.rows) {
                for (col in 0 until it.columns) {
                    val y =
                        aboveSize.rows * cellSize.height + dividerSectionHeight + row * cellSize.height
                    val x = belowLeftMargin + col * cellSize.width
                    val r = Rect(x, y, x + cellSize.width, y + cellSize.height)
                    canvas.drawRect(r, paint)
                }
            }
        }

    }

    fun drawCells(items: List<KnitArrangeCell>): Bitmap {
        val canvas = Canvas(bitmap)

        for (item in items) {
            // 如果下表格为 null，但是单元格却是下表格的单元格，就跳过
            if (belowSize == null && !item.above) continue
            drawCell(canvas, item)
        }

        return bitmap
    }

    private fun drawCell(canvas: Canvas, cell: KnitArrangeCell) {
        val (x, y) = findLocation(cell)
        canvas.drawText(cell.content, x, y, textPaint)
    }

    private fun findLocation(cell: KnitArrangeCell): Pair<Float, Float> {
        return if (cell.above) {
            findAboveLocation(cell)
        } else {
            findBelowLocation(cell)
        }
    }

    private fun findAboveLocation(cell: KnitArrangeCell): Pair<Float, Float> {
        var offsetX = aboveLeftMargin + cell.x * cellSize.width
        var offsetY = cell.y * cellSize.height

        val (dx, dy) = getOffsetInCell(cell.content)

        offsetX += dx
        offsetY += dy

        return Pair(offsetX.toFloat(), offsetY.toFloat())
    }

    private fun findBelowLocation(cell: KnitArrangeCell): Pair<Float, Float> {
        var offsetX = belowLeftMargin + cell.x * cellSize.width
        var offsetY =
            aboveSize.rows * cellSize.height + dividerSectionHeight + cell.y * cellSize.height

        val (dx, dy) = getOffsetInCell(cell.content)
        offsetX += dx
        offsetY += dy

        return Pair(offsetX.toFloat(), offsetY.toFloat())
    }

    private fun getOffsetInCell(content: String, size: Size = cellSize): Pair<Int, Int> {
        val bounds = Rect()
        textPaint.getTextBounds(content, 0, content.length, bounds)
        val dx = (size.width - bounds.width()) / 2
        val dy = (size.height - bounds.height()) / 2 + bounds.height()

        return Pair(dx, dy)
    }


}


data class KnitArrangeCell(
    val x: Int,
    val y: Int,
    val content: String,
    val above: Boolean = true,
)